package top.lucky.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.sql.Time;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
public class DateUtil {

    private static transient int gregorianCutoverYear = 1582;
    /** 闰年中每月天数 */
    private static final int[] DAYS_P_MONTH_LY= {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    /** 非闰年中每月天数 */
    private static final int[] DAYS_P_MONTH_CY= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    /** 代表数组里的年、月、日 */
    private static final int Y = 0, M = 1, D = 2;
    public static final String UNION_YMD_PATTERN = "yyyyMMdd";
    public static final String YYYYMMDD = "yyyy.MM.dd";
    public static final String YYYY_MM_DD = "yyyy/MM/dd";
    public static final String YYYY_MM_DD_HH_mm_ss = "yyyy/MM/dd HH:mm:ss";
    public static final String YYYY_MM_DD_HYPHEN = "yyyy-MM-dd";
    public static final String YYYY_MM_DD_HYPHEN_HH_mm = "yyyy-MM-dd HH:mm";
    public static final String YYYY_MM_DD_HYPHEN_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
    public static final String YYYY_MM_DD_HYPHEN_HH_mm_ss_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String YYYY_MM_DD_CHINESE_CHARACTERS = "yyyy年MM月dd日";
    public final static String YYYY_MM_DD_HH_mm_ss_2 = "yyyyMMddHHmmss";
    public final static String YYYY_MM_DD_HH_00_00 = "yyyy-MM-dd HH:00:00";
    public final static String YYYY_MM_DD_HH_00 = "yyyyMMddHH00";
    public final static String YYYY_MM_DD_00_00_00 = "yyyy-MM-dd 00:00:00";
    public final static String YYYY_MM_DD_HH_mm_ss_ss = "yyyyMMddHHmmssSSS";

    public static Date getMinDate() {
        return dateParse(YYYY_MM_DD_HYPHEN, "1970-01-01");
    }

    public static Date getMaxDate() {
        return dateParse(YYYY_MM_DD_HYPHEN, "2099-01-01");
    }

    
    public static String dateFormat (String pattern, Date date) {
        if (StringUtils.isBlank(pattern) || date == null) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        return dateFormat.format(date);
    }

    public static Date dateParse(String pattern, String dateStr) {
        if (StringUtils.isBlank(pattern) || StringUtils.isBlank(dateStr)) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        try {
            return dateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.warn("DateUtil dateParse error:"+ ExceptionUtils.getStackTrace(e));
        }
        return null;
    }

    /**
     * 将代表日期的字符串分割为代表年月日的整形数组
     * @param date
     * @return
     */
    public static int[] splitYMD(String date){
        date = date.replace("-", "");
        int[] ymd = {0, 0, 0};
        ymd[Y] = Integer.parseInt(date.substring(0, 4));
        ymd[M] = Integer.parseInt(date.substring(4, 6));
        ymd[D] = Integer.parseInt(date.substring(6, 8));
        return ymd;
    }

    /**
     * 检查传入的参数代表的年份是否为闰年
     * @param year
     * @return
     */
    public static boolean isLeapYear(int year) {
        return year >= gregorianCutoverYear ? ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))) : (year%4 == 0);
    }

    /**
     * 日期加1天
     * @param year
     * @param month
     * @param day
     * @return
     */
    private static int[] addOneDay(int year, int month, int day){
        if(isLeapYear( year )){
            day++;
            if( day > DAYS_P_MONTH_LY[month -1 ] ){
                month++;
                if(month > 12){
                    year++;
                    month = 1;
                }
                day = 1;
            }
        }else{
            day++;
            if( day > DAYS_P_MONTH_CY[month -1 ] ){
                month++;
                if(month > 12){
                    year++;
                    month = 1;
                }
                day = 1;
            }
        }
        int[] ymd = {year, month, day};
        return ymd;
    }

    /**
     * 将不足两位的月份或日期补足为两位
     * @param decimal
     * @return
     */
    public static String formatMonthDay(int decimal){
        DecimalFormat df = new DecimalFormat("00");
        return df.format( decimal );
    }

    /**
     * 将不足四位的年份补足为四位
     * @param decimal
     * @return
     */
    public static String formatYear(int decimal){
        DecimalFormat df = new DecimalFormat("0000");
        return df.format( decimal );
    }

    /**
     * 计算两个日期之间相隔的天数
     * @param begin
     * @param end
     * @return
     * @throws ParseException
     */
    public static long countDay(String begin,String end){
        SimpleDateFormat format = new SimpleDateFormat(YYYY_MM_DD_HYPHEN);
        Date beginDate , endDate;
        long day = 0;
        try {
            beginDate= format.parse(begin);
            endDate=  format.parse(end);
            day=countDay(beginDate, endDate);
        } catch (ParseException e) {
            log.warn("DateUtil countDay error:"+ ExceptionUtils.getStackTrace(e));
        }
        return day;
    }


    /**
     * 计算两个日期之间相隔的天数
     * @param beginDate
     * @param endDate
     * @return
     * @throws ParseException
     */
    public static long countDay(Date beginDate,Date endDate){
        return (endDate.getTime() - beginDate.getTime()) / (24*60*60*1000);
    }

    /**
     * 以循环的方式计算日期
     * @param beginDate endDate
     * @return
     */
    public static List<String> getEveryday(String beginDate , String endDate){
        long days = countDay(beginDate, endDate);
        int[] ymd = splitYMD( beginDate );
        List<String> everyDays = new ArrayList<String>();
        everyDays.add(beginDate);
        for(int i = 0; i < days; i++){
            ymd = addOneDay(ymd[Y], ymd[M], ymd[D]);
            everyDays.add(formatYear(ymd[Y])+"-"+formatMonthDay(ymd[M])+"-"+formatMonthDay(ymd[D]));
        }
        return everyDays;
    }

    /*
     * 将时间转换为时间戳
     */
    public static long dateToStamp(String s){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtil.UNION_YMD_PATTERN);
        long day = 0;
        try {
            Date  date = simpleDateFormat.parse(s);
            day=date.getTime();
            return day;
        } catch (ParseException e) {
            log.warn("DateUtil countDay error:"+ ExceptionUtils.getStackTrace(e));
        }
        return day;
    }

    /**
     * 将接口返回的180203转为18:02:03
     * @param str
     * @return
     */
    public static Time timeConvertion(String str) {
        Time time = null;
        try {
            SimpleDateFormat df = new SimpleDateFormat("HHmmss");
            time = new Time(df.parse(str).getTime());
        } catch (ParseException e) {
            log.warn("DateUtil time Convertion error:"+ ExceptionUtils.getStackTrace(e));
        }
        return time;
    }

    /**
     * 日期格式化
     * @param sourPattern
     * @param tagPattern
     * @param date
     * @return
     */
    public static String strDateFormat (String sourPattern,String tagPattern, String date) {
        if (StringUtils.isBlank(sourPattern) || date == null || StringUtils.isBlank(tagPattern)) {
            return null;
        }
        return dateFormat(tagPattern,dateParse(sourPattern,date));
    }
}
